/**************************************************************************** 
 * Meta，一个轻量级的静态分区Hypervisor 
 *
 * 版权(c) , 2022-
 *
 * 作者:
 *      Tupelo Shen <shenwanjiang2013@163.com>
 *
 * Meta是一个自由软件，你可以在遵循GNU GPLv2协议的条件下，重新修改并发布它。
 *
 ***************************************************************************/

#include <arch/vgic.h>

#include <cpu.h>
#include <vm.h>

/* 虚拟GIC相关事件 */
enum VGIC_EVENTS {
    VGIC_UPDATE_ENABLE,
    VGIC_ROUTE,
    VGIC_INJECT,
    VGIC_SET_REG
};

/* 虚拟GIC-消息数据处理宏 */
#define VGIC_MSG_DATA(VM_ID, VGICRID, INT_ID, REG, VAL)                 \
    (((uint64_t)(VM_ID) << 48) | (((uint64_t)(VGICRID)&0xffff) << 32) | \
     (((INT_ID)&0x7fff) << 16) | (((REG)&0xff) << 8) | ((VAL)&0xff))
#define VGIC_MSG_VM(DATA)       ((DATA) >> 48)
#define VGIC_MSG_VGICRID(DATA)  (((DATA) >> 32) & 0xffff)
#define VGIC_MSG_INTID(DATA)    (((DATA) >> 16) & 0x7fff)
#define VGIC_MSG_REG(DATA)      (((DATA) >> 8) & 0xff)
#define VGIC_MSG_VAL(DATA)      ((DATA)&0xff)

#define GICD_IS_REG(REG, offset)            \
    (((offset) >= offsetof(struct gicd_hw, REG)) && \
     (offset) < (offsetof(struct gicd_hw, REG) + sizeof(gicd.REG)))
#define GICD_REG_GROUP(REG) ((offsetof(struct gicd_hw, REG) & 0xff80) >> 7)
#define GICD_REG_MASK(ADDR) ((ADDR)&(GIC_VERSION == GICV2 ? 0xfffULL : 0xffffULL))
#define GICD_REG_IND(REG)   (offsetof(struct gicd_hw, REG) & 0x7f)

/* 中断使能（全局）*/
#define VGIC_ENABLE_MASK \
    ((GIC_VERSION == GICV2) ? GICD_CTLR_EN_BIT : GICD_CTLR_ENA_BIT)

/****************************************************************************
 ****                       私有函数接口                                 ****
 ****************************************************************************/

static inline int64_t       gich_get_lr(struct vgic_int *interrupt, uint64_t *lr);

static void                 vgic_handle_trapped_eoir(struct vcpu *vcpu);
static void                 vgic_refill_lrs(struct vcpu *vcpu);
static inline struct vgic_int* vgic_get_int(
                                    struct vcpu *vcpu,
                                    irqid_t     int_id,
                                    vcpuid_t    vgicr_id
                                    );
static bool                 vgic_owns(
                                    struct vcpu *vcpu,
                                    struct vgic_int *interrupt
                                    );
static inline void          vgic_write_lr(
                                struct vcpu *vcpu,
                                struct vgic_int *interrupt,
                                size_t lr_ind
                                );
static inline uint8_t       vgic_get_state(struct vgic_int *interrupt);
static inline bool          vgic_int_is_hw(struct vgic_int *interrupt);
static void                 vgic_route(
                                    struct vcpu *vcpu,
                                    struct vgic_int *interrupt
                                    );
static void                 vgic_int_set_field(
                                    struct vgic_reg_handler_info *handlers,
                                    struct vcpu *vcpu,
                                    struct vgic_int *interrupt,
                                    uint64_t data
                                    );
static inline void          vgic_update_enable(struct vcpu *vcpu);
static void                 vgic_eoir_highest_spilled_active(struct vcpu *vcpu);

static void                 vgic_ipi_handler(uint32_t event, uint64_t data);
CPU_MSG_HANDLER(vgic_ipi_handler, VGIC_IPI_ID);


/****************************************************************************
 ****                       私有函数接口                                 ****
 ****************************************************************************/

/* 更新虚拟中断使能 */
bool vgic_int_update_enable(struct vcpu *vcpu, struct vgic_int *interrupt, bool enable)
{
    if (GIC_VERSION == GICV2 && gic_is_sgi(interrupt->id)) {
        return false;
    }

    if (enable != interrupt->enabled) {
        interrupt->enabled = enable;
        return true;
    } else {
        return false;
    }
}
/* 使能虚拟中断对应的硬件中断 */
void vgic_int_enable_hw(struct vcpu *vcpu, struct vgic_int *interrupt)
{
#if (GIC_VERSION != GICV2)
    if (gic_is_priv(interrupt->id)) {
        gicr_set_enable(interrupt->id, interrupt->enabled,
                        interrupt->phys.redist);
    } else {
        gicd_set_enable(interrupt->id, interrupt->enabled);
    }
#else
    gic_set_enable(interrupt->id, interrupt->enabled);
#endif
}
/* 获取虚拟中断使能 */
uint64_t vgic_int_get_enable(struct vcpu *vcpu, struct vgic_int *interrupt)
{
    return (uint64_t)interrupt->enabled;
}
/* 设置虚拟中断使能 */
bool vgic_int_set_enable(struct vcpu *vcpu, struct vgic_int *interrupt, uint64_t data)
{
    if (!data)
        return false;
    else
        return vgic_int_update_enable(vcpu, interrupt, true);
}
/* 清除虚拟中断使能 */
bool vgic_int_clear_enable(struct vcpu *vcpu, struct vgic_int *interrupt, uint64_t data)
{
    if (!data)
        return false;
    else
        return vgic_int_update_enable(vcpu, interrupt, false);
}

/****************************************************************************/
/* 更新虚拟中断挂起 */
bool vgic_int_update_pend(struct vcpu *vcpu, struct vgic_int *interrupt, bool pend)
{
    if (GIC_VERSION == GICV2 && gic_is_sgi(interrupt->id)) {
        return false;
    }

    if (pend ^ !!(interrupt->state & PEND)) {
        if (pend)
            interrupt->state |= PEND;
        else
            interrupt->state &= ~PEND;
        return true;
    } else {
        return false;
    }
}
/* 获取虚拟中断挂起 */
uint64_t vgic_int_get_pend(struct vcpu *vcpu, struct vgic_int *interrupt)
{
    return (interrupt->state & PEND) ? 1 : 0;
}
/* 设置虚拟中断挂起 */
bool vgic_int_set_pend(struct vcpu *vcpu, struct vgic_int *interrupt, uint64_t data)
{
    if (!data)
        return false;
    else
        return vgic_int_update_pend(vcpu, interrupt, true);
}
/* 清除虚拟中断挂起 */
bool vgic_int_clear_pend(struct vcpu *vcpu, struct vgic_int *interrupt, uint64_t data)
{
    if (!data)
        return false;
    else
        return vgic_int_update_pend(vcpu, interrupt, false);
}
/* 设置虚拟中断对应的硬件中断挂起状态 */
void vgic_int_state_hw(struct vcpu *vcpu, struct vgic_int *interrupt)
{
    uint8_t state = interrupt->state == PEND ? ACT : interrupt->state;
    bool pend = (state & PEND) != 0;
    bool act = (state & ACT) != 0;
#if (GIC_VERSION != GICV2)
    if (gic_is_priv(interrupt->id)) {
        gicr_set_act(interrupt->id, act, interrupt->phys.redist);
        gicr_set_pend(interrupt->id, pend, interrupt->phys.redist);
    } else {
        gicd_set_act(interrupt->id, act);
        gicd_set_pend(interrupt->id, pend);
    }
#else
    gicd_set_act(interrupt->id, act);
    gicd_set_pend(interrupt->id, pend);
#endif
}

/****************************************************************************/
/* 更新虚拟中断激活 */
bool vgic_int_update_act(struct vcpu *vcpu, struct vgic_int *interrupt, bool act)
{
    if (act ^ !!(interrupt->state & ACT)) {
        if (act)
            interrupt->state |= ACT;
        else
            interrupt->state &= ~ACT;
        return true;
    } else {
        return false;
    }
}
/* 获取虚拟中断激活 */
uint64_t vgic_int_get_act(struct vcpu *vcpu, struct vgic_int *interrupt)
{
    return (interrupt->state & ACT) ? 1 : 0;
}
/* 设置虚拟中断激活 */
bool vgic_int_set_act(struct vcpu *vcpu, struct vgic_int *interrupt, uint64_t data)
{
    if (!data)
        return false;
    else
        return vgic_int_update_act(vcpu, interrupt, true);
}
/* 清除虚拟中断激活 */
bool vgic_int_clear_act(struct vcpu *vcpu, struct vgic_int *interrupt, uint64_t data)
{
    if (!data)
        return false;
    else
        return vgic_int_update_act(vcpu, interrupt, false);
}

/****************************************************************************/
/* 获取虚拟中断配置 */
uint64_t vgic_int_get_cfg(struct vcpu *vcpu, struct vgic_int *interrupt)
{
    return (uint64_t)interrupt->cfg;
}
/* 设置虚拟中断配置 */
bool vgic_int_set_cfg(struct vcpu *vcpu, struct vgic_int *interrupt, uint64_t cfg)
{
    uint8_t prev_cfg = interrupt->cfg;
    interrupt->cfg = (uint8_t)cfg;
    return prev_cfg != cfg;
}
/* 设置虚拟中断对应的硬件中断配置 */
void vgic_int_set_cfg_hw(struct vcpu *vcpu, struct vgic_int *interrupt)
{
#if (GIC_VERSION != GICV2)
    if (gic_is_priv(interrupt->id)) {
        gicr_set_icfgr(interrupt->id, interrupt->cfg, interrupt->phys.redist);
    } else {
        gicd_set_icfgr(interrupt->id, interrupt->cfg);
    }
#else
    gic_set_icfgr(interrupt->id, interrupt->cfg);
#endif
}

/****************************************************************************/
/* 获取虚拟中断优先级 */
uint64_t vgic_int_get_prio(struct vcpu *vcpu, struct vgic_int *interrupt)
{
    return (uint64_t)interrupt->prio;
}
/* 设置虚拟中断优先级 */
bool vgic_int_set_prio(struct vcpu *vcpu, struct vgic_int *interrupt, uint64_t prio)
{
    uint8_t prev_prio = interrupt->prio;
    interrupt->prio = (uint8_t)prio;
    return prev_prio != prio;
}
/* 设置虚拟中断对应的硬件中断优先级 */
void vgic_int_set_prio_hw(struct vcpu *vcpu, struct vgic_int *interrupt)
{
#if (GIC_VERSION != GICV2)
    if (gic_is_priv(interrupt->id)) {
        gicr_set_prio(interrupt->id, interrupt->prio, interrupt->phys.redist);
    } else {
        gicd_set_prio(interrupt->id, interrupt->prio);
    }
#else
    gic_set_prio(interrupt->id, interrupt->prio);
#endif
}

/* 模拟写寄存器 */
void vgic_emul_razwi(
        struct  emul_access *acc,
        struct  vgic_reg_handler_info *handlers,
        bool    gicr_access,
        cpuid_t vgicr_id)
{
    if (!acc->write) vcpu_writereg(cpu.vcpu, acc->reg, 0);
}
/****************************************************************************/

/* 模拟中断使能寄存器 */
struct vgic_reg_handler_info isenabler_info = {
    vgic_emul_generic_access,
    0b0100,                         /* 4字节对齐 */
    VGIC_ISENABLER_ID,
    offsetof(struct gicd_hw, ISENABLER),
    1,
    vgic_int_get_enable,
    vgic_int_set_enable,
    vgic_int_enable_hw,
};

/* 模拟中断挂起设置寄存器 */
struct vgic_reg_handler_info ispendr_info = {
    vgic_emul_generic_access,
    0b0100,
    VGIC_ISPENDR_ID,
    offsetof(struct gicd_hw, ISPENDR),
    1,
    vgic_int_get_pend,
    vgic_int_set_pend,
    vgic_int_state_hw,
};

/* 模拟中断激活设置寄存器 */
struct vgic_reg_handler_info isactiver_info = {
    vgic_emul_generic_access,
    0b0100,
    VGIC_ISACTIVER_ID,
    offsetof(struct gicd_hw, ISACTIVER),
    1,
    vgic_int_get_act,
    vgic_int_set_act,
    vgic_int_state_hw,
};

/* 模拟中断使能清除寄存器 */
struct vgic_reg_handler_info icenabler_info = {
    vgic_emul_generic_access,
    0b0100,
    VGIC_ICENABLER_ID,
    offsetof(struct gicd_hw, ICENABLER),
    1,
    vgic_int_get_enable,
    vgic_int_clear_enable,
    vgic_int_enable_hw,
};

/* 模拟中断挂起清除寄存器 */
struct vgic_reg_handler_info icpendr_info = {
    vgic_emul_generic_access,
    0b0100,
    VGIC_ICPENDR_ID,
    offsetof(struct gicd_hw, ICPENDR),
    1,
    vgic_int_get_pend,
    vgic_int_clear_pend,
    vgic_int_state_hw,
};

/* 模拟中断激活清除寄存器 */
struct vgic_reg_handler_info iactiver_info = {
    vgic_emul_generic_access,
    0b0100,
    VGIC_ICACTIVER_ID,
    offsetof(struct gicd_hw, ICACTIVER),
    1,
    vgic_int_get_act,
    vgic_int_clear_act,
    vgic_int_state_hw,
};

/* 模拟中断配置寄存器 */
struct vgic_reg_handler_info icfgr_info = {
    vgic_emul_generic_access,
    0b0100,
    VGIC_ICFGR_ID,
    offsetof(struct gicd_hw, ICFGR),
    2,
    vgic_int_get_cfg,
    vgic_int_set_cfg,
    vgic_int_set_cfg_hw,
};

/* 模拟中断优先级寄存器 */
struct vgic_reg_handler_info ipriorityr_info = {
    vgic_emul_generic_access,
    0b0101,
    VGIC_IPRIORITYR_ID,
    offsetof(struct gicd_hw, IPRIORITYR),
    8,
    vgic_int_get_prio,
    vgic_int_set_prio,
    vgic_int_set_prio_hw,
};

struct vgic_reg_handler_info vgicd_misc_info = {
    vgicd_emul_misc_access,
    0b0100,
};

struct vgic_reg_handler_info vgicd_pidr_info = {
    vgicd_emul_pidr_access,
    0b0100,
};

struct vgic_reg_handler_info razwi_info = {
    vgic_emul_razwi,
    0b0100,
};

__attribute__((weak)) struct vgic_reg_handler_info itargetr_info = {
    vgic_emul_razwi,
    0b0101,
};

__attribute__((weak)) struct vgic_reg_handler_info sgir_info = {
    vgic_emul_razwi,
    0b0100,
};

__attribute__((weak)) struct vgic_reg_handler_info irouter_info = {
    vgic_emul_razwi,
    0b0100,
};
struct vgic_reg_handler_info *reg_handler_info_table[VGIC_REG_HANDLER_ID_NUM] =
{
    [VGIC_ISENABLER_ID]     = &isenabler_info,
    [VGIC_ISPENDR_ID]       = &ispendr_info,
    [VGIC_ISACTIVER_ID]     = &isactiver_info,
    [VGIC_ICENABLER_ID]     = &icenabler_info,
    [VGIC_ICPENDR_ID]       = &icpendr_info,
    [VGIC_ICACTIVER_ID]     = &iactiver_info,
    [VGIC_ICFGR_ID]         = &icfgr_info,
    [VGIC_IROUTER_ID]       = &irouter_info,
    [VGIC_IPRIORITYR_ID]    = &ipriorityr_info,
    [VGIC_ITARGETSR_ID]     = &itargetr_info
};
struct vgic_reg_handler_info
        *vgic_get_reg_handler_info(enum vgic_reg_handler_info_id id)
{
    if (id < VGIC_REG_HANDLER_ID_NUM) {
        return reg_handler_info_table[id];
    } else {
        return NULL;
    }
}

/****************************************************************************
 ****                       公共函数定义                                 ****
 ****************************************************************************/
/**
 * 功能描述: 维护中断处理函数（默认中断号为25）
 * 入口参数: arg: 为了函数保持统一，添加的参数，未使用
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void gic_maintenance_handler(irqid_t irq_id)
{
    uint32_t misr = gich_get_misr();

    /* 维护中断（EOI），说明已经有中断处理完成 */
    if (misr & GICH_MISR_EOI) {
        vgic_handle_trapped_eoir(cpu.vcpu);
    }

    /* 维护中断（No Pending）产生，说明虚拟中断列表寄存器为空，可以继续填充 */
    if (misr & GICH_MISR_NP) {
        vgic_refill_lrs(cpu.vcpu);
    }

    /* 维护中断（List Register Entry Not Present），说明列表寄存器满 
     * TODO: 未完成
     */
    if (misr & GICH_MISR_LRENP) {
        uint32_t hcr_el2 = 0;
        while (hcr_el2 = gich_get_hcr(), hcr_el2 & GICH_HCR_EOICount_MASK) {
            vgic_eoir_highest_spilled_active(cpu.vcpu);
            hcr_el2 -= (1U << GICH_HCR_EOICount_OFF);
            gich_set_hcr(hcr_el2);
        }
    }

    /* TODO: 其它维护中断是否要处理 */
}

/**
 * 功能描述: 将中断添加到列表寄存器中，并在虚拟核的私有列表寄存器中记录
 * 入口参数: vcpu:          指向虚拟核数据结构的指针
 *           interrupt:     指向要添加的虚拟中断
 * 出口参数: void
 * 返 回 值: bool - 如果添加成功返回true，添加失败则返回false
 * 修改日期: 2022-09-21
 */
bool vgic_add_lr(struct vcpu *vcpu, struct vgic_int *interrupt)
{
    bool ret = false;

    /* 如果中断被禁止，或已经在列表寄存器中，则直接返回false */
    if (!interrupt->enabled || interrupt->in_lr) {
        return ret;
    }

    /* 读取 empty list register status register, 查看是否有空列表项 */
    ssize_t lr_ind = -1;
    uint64_t elrsr = gich_get_elrsr();
    for (size_t i = 0; i < g_num_lrs; i++) {
        if (bit64_get(elrsr, i)) {
            lr_ind = i;
            break;
        }
    }

    /* 没有空的列表寄存器项 */
    if (lr_ind < 0) {
        unsigned    min_prio_pend = 0, min_prio_act = 0;
        size_t      pend_found = 0, act_found = 0;
        ssize_t     pend_ind = -1, act_ind = -1;

        for (int i = 0; i < g_num_lrs; i++) {
            unsigned long lr = gich_read_lr(i);
            unsigned lr_prio = (lr & GICH_LR_PRIO_MSK) >> GICH_LR_PRIO_OFF;
            unsigned lr_state = (lr & GICH_LR_STATE_MSK);

            if (lr_state & GICH_LR_STATE_ACT) {
                if (lr_prio > min_prio_act) {
                    min_prio_act = lr_prio;
                    act_ind = i;
                }
                pend_found++;
            } else if (lr_state & GICH_LR_STATE_PND) {
                if (lr_prio > min_prio_pend) {
                    min_prio_pend = lr_prio;
                    pend_ind = i;
                }
                act_found++;
            }
        }

        if (pend_found > 1) {
            lr_ind = pend_ind;
        } else {
            lr_ind = act_ind;
        }

        if (lr_ind >= 0) {
            struct vgic_int *spilled_int =
                vgic_get_int(vcpu, GICH_LR_VID(gich_read_lr(lr_ind)), vcpu->id);

            if (spilled_int != NULL) {
                // TODO: possible deadlock?
                spin_lock(&spilled_int->lock);
                vgic_remove_lr(vcpu, spilled_int);
                vgic_yield_ownership(vcpu, spilled_int);
                spin_unlock(&spilled_int->lock);
            }
        }
    }

    /* 有空列表寄存器项，则将中断添加到列表寄存器中 */
    if (lr_ind >= 0) {
        vgic_write_lr(vcpu, interrupt, lr_ind);
        ret = true;
    } else {
        /* 打开维护中断，等待guest处理完所有中断，立即通知hypervisor再添加列表 */
        if (vgic_get_state(interrupt) & PEND) {
            gich_set_hcr(gich_get_hcr() | GICH_HCR_NPIE_BIT);
        }
    }

    return ret;
}

/**
 * 功能描述: 从列表寄存器中移除中断
 * 入口参数: vcpu:          指向虚拟核的数据结构
 *           interrupt:     要处理中断的数据结构的指针
 * 出口参数: void
 * 返 回 值: bool:     如果移除成功则返回true，否则返回false
 * 修改日期: 2022-09-21
 */
bool vgic_remove_lr(struct vcpu *vcpu, struct vgic_int *interrupt)
{
    bool ret = false;

    /* 参数检查：如果中断和虚拟核不匹配、或中断不在列表中，则直接返回false */
    if (!vgic_owns(vcpu, interrupt) || !interrupt->in_lr) {
        return ret;
    }

    /* 根据中断信息，从列表中取出对应的寄存器的值;
     * 并将该寄存器清零
     */
    unsigned long lr_val = 0;
    ssize_t lr_ind = -1;
    if ((lr_ind = gich_get_lr(interrupt, &lr_val)) >= 0) {
        gich_write_lr(lr_ind, 0);
    }

    interrupt->in_lr = false;

    /* 如果移除的中断是pending且中断被使能，需要在中断数据结构中保留该中断。
     * 所以，应该使能EPIE标志位，使能No Pending维护中断。待guest OS处理完后，
     * 及时通知hypervisor将中断添加到列表寄存器中。这样，可以提高中断处理效率。
     */
    if (GICH_LR_STATE(lr_val) != INV) {
        interrupt->state = GICH_LR_STATE(lr_val);
#if (GIC_VERSION == GICV2)
        if (interrupt->id < GIC_MAX_SGIS) {
            if (interrupt->state & ACT) {
                interrupt->sgi.act = GICH_LR_CPUID(lr_val);
            } else if (interrupt->state & PEND) {
                interrupt->sgi.pend |= (1U << GICH_LR_CPUID(lr_val));
            }
        }
#endif
        if ((interrupt->state & PEND) && interrupt->enabled) {
            gich_set_hcr(gich_get_hcr() | GICH_HCR_NPIE_BIT);
        }

        ret = true;
    }

    return ret;
}

/**
 * 功能描述: 虚拟核vcpu让出中断所有权
 * 入口参数: struct vcpu *vcpu:          指向虚拟核的数据结构
 *           struct vgic_int *interrupt: 要处理中断的数据结构的指针
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void vgic_yield_ownership(struct vcpu *vcpu, struct vgic_int *interrupt)
{
    if ((GIC_VERSION == GICV2 && gic_is_priv(interrupt->id)) ||
        !vgic_owns(vcpu, interrupt) || interrupt->in_lr ||
        (vgic_get_state(interrupt) & ACT)) {
        return;
    }

    interrupt->owner = NULL;
}

/**
 * 功能描述: 虚拟核vcpu获取中断所有权
 * 入口参数: struct vcpu *vcpu:          指向虚拟核的数据结构
 *           struct vgic_int *interrupt: 要处理中断的数据结构的指针
 * 出口参数: void
 * 返 回 值: bool - 成功返回ture；否则返回false
 * 修改日期: 2022-09-21
 */
bool vgic_get_ownership(struct vcpu *vcpu, struct vgic_int *interrupt)
{
    bool ret = false;

    if (interrupt->owner == vcpu) {
        ret = true;
    } else if (interrupt->owner == NULL) {
        interrupt->owner = vcpu;
        ret = true;
    }

    return ret;
}

/**
 * 功能描述: 将物理中断转换成虚拟中断，然后注入到VM中
 *           分为两种情况：
 *           1. 如果是虚拟中断是由硬件管理的中断，则添加到列表寄存器
 *           2. 如果是软件中断
 * 入口参数: vgicd, 虚拟GICD
 *           id,    物理中断号
 *           source,虚拟中断号   
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void vgic_inject(struct vgicd *vgicd, irqid_t id, vcpuid_t source)
{
    struct vgic_int *interrupt = vgic_get_int(cpu.vcpu, id, cpu.vcpu->id);
    if (interrupt != NULL) {
        if (vgic_int_is_hw(interrupt)) {
            spin_lock(&interrupt->lock);
            interrupt->owner = cpu.vcpu;
            interrupt->state = PEND;
            interrupt->in_lr = false;
            vgic_route(cpu.vcpu, interrupt);
            spin_unlock(&interrupt->lock);
        } else {
            if (GIC_VERSION == GICV2 && gic_is_sgi(id)) {
                // TODO: GICv2版本的虚拟软中断注入方法未实现
                // vgic_inject_sgi(cpu.vcpu, interrupt, source);
            } else {
                vgic_int_set_field(&ispendr_info, cpu.vcpu, interrupt, true);
            }
        }
    }
}

/**
 * 功能描述: vgic模拟寄存器访问
 * 入口参数: acc,       指向要访问的寄存器信息的指针
 *           handlers,  寄存器操作函数指针
 *           gicr_access,
 *           vgicr_id,  虚拟gicr寄存器的ID
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void vgic_emul_generic_access(struct emul_access *acc,
                              struct vgic_reg_handler_info *handlers,
                              bool      gicr_access,
                              cpuid_t   vgicr_id)
{
    size_t      field_width = handlers->field_width;
    size_t      first_int =
        (GICD_REG_MASK(acc->addr) - handlers->regroup_base) * 8 / field_width;
    uint64_t    val = acc->write ? vcpu_readreg(cpu.vcpu, acc->reg) : 0;
    uint64_t    mask = (1ull << field_width) - 1;
    bool valid_access =
        (GIC_VERSION == GICV2) || !(gicr_access ^ gic_is_priv(first_int));

    if (valid_access) {
        for (size_t i = 0; i < ((acc->width * 8) / field_width); i++) {
            struct vgic_int *interrupt =
                vgic_get_int(cpu.vcpu, first_int + i, vgicr_id);
            if (interrupt == NULL) break;
            if (acc->write) {
                uint64_t data = bit64_extract(val, i * field_width, field_width);
                vgic_int_set_field(handlers, cpu.vcpu, interrupt, data);
            } else {
                val |= (handlers->read_field(cpu.vcpu, interrupt) & mask)
                       << (i * field_width);
            }
        }
    }

    if (!acc->write) {
        vcpu_writereg(cpu.vcpu, acc->reg, val);
    }
}

/**
 * 功能描述: vgicd模拟寄存器访问
 * 入口参数: acc,       指向要访问的寄存器信息的指针
 *           handlers,  寄存器操作函数指针
 *           gicd_access,
 *           vgicd_id,  虚拟gicr寄存器的ID
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void vgicd_emul_misc_access(struct  emul_access *acc,
                            struct  vgic_reg_handler_info *handlers,
                            bool    gicd_access,
                            cpuid_t vgicd_id)
{
    struct vgicd *vgicd = &cpu.vcpu->vm->arch.vgicd;
    unsigned reg = acc->addr & 0x7F;

    switch (reg) {
        case GICD_REG_IND(CTLR):
            if (acc->write) {
                uint32_t prev_ctrl = vgicd->CTLR;
                vgicd->CTLR =
                    vcpu_readreg(cpu.vcpu, acc->reg) & VGIC_ENABLE_MASK;
                if (prev_ctrl ^ vgicd->CTLR) {
                    vgic_update_enable(cpu.vcpu);
                    struct cpu_msg msg = {
                        VGIC_IPI_ID, 
                        VGIC_UPDATE_ENABLE,
                        VGIC_MSG_DATA(cpu.vcpu->vm->id, 0, 0, 0, 0)};
                    vm_msg_broadcast(cpu.vcpu->vm, &msg);
                }
            } else {
                vcpu_writereg(cpu.vcpu, acc->reg,
                              vgicd->CTLR | GICD_CTLR_ARE_NS_BIT);
            }
            break;
        case GICD_REG_IND(TYPER):
            if (!acc->write) {
                vcpu_writereg(cpu.vcpu, acc->reg, vgicd->TYPER);
            }
            break;
        case GICD_REG_IND(IIDR):
            if (!acc->write) {
                vcpu_writereg(cpu.vcpu, acc->reg, vgicd->IIDR);
            }
            break;
    }
}

/**
 * 功能描述: vgicd模拟ID寄存器访问
 * 入口参数: acc,       指向要访问的寄存器信息的指针
 *           handlers,  寄存器操作函数指针
 *           gicd_access,
 *           vgicd_id,  虚拟gicr寄存器的ID
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void vgicd_emul_pidr_access(struct  emul_access *acc,
                            struct  vgic_reg_handler_info *handlers,
                            bool    gicd_access,
                            cpuid_t vgicd_id)
{
    if (!acc->write) {
        vcpu_writereg(cpu.vcpu, acc->reg,
                      gicd.ID[((acc->addr & 0xff) - 0xd0) / 4]);
    }
}

/**
 * 功能描述: vgic寄存器是否对齐
 * 入口参数: acc,       指向要访问的寄存器信息的指针
 *           handlers,  寄存器操作函数指针
 * 出口参数: void
 * 返 回 值: bool,      对齐返回true；否则返回false
 * 修改日期: 2022-09-21
 */
bool vgic_check_reg_alignment(struct emul_access *acc,
                              struct vgic_reg_handler_info *handlers)
{
    if (!(handlers->alignment & acc->width) ||
        ((acc->addr & (acc->width - 1)) != 0)) {
        return false;
    } else {
        return true;
    }
}

/**
 * 功能描述: vgicd模拟处理函数
 * 入口参数: acc,       指向要访问的寄存器信息的指针
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
bool vgicd_emul_handler(struct emul_access *acc)
{
    struct vgic_reg_handler_info *handler_info = NULL;
    switch (GICD_REG_MASK(acc->addr) >> 7) {
        case GICD_REG_GROUP(CTLR):
            handler_info = &vgicd_misc_info;
            break;
        case GICD_REG_GROUP(ISENABLER):
            handler_info = &isenabler_info;
            break;
        case GICD_REG_GROUP(ISPENDR):
            handler_info = &ispendr_info;
            break;
        case GICD_REG_GROUP(ISACTIVER):
            handler_info = &isactiver_info;
            break;
        case GICD_REG_GROUP(ICENABLER):
            handler_info = &icenabler_info;
            break;
        case GICD_REG_GROUP(ICPENDR):
            handler_info = &icpendr_info;
            break;
        case GICD_REG_GROUP(ICACTIVER):
            handler_info = &iactiver_info;
            break;
        case GICD_REG_GROUP(ICFGR):
            handler_info = &icfgr_info;
            break;
        case GICD_REG_GROUP(SGIR):
            handler_info = &sgir_info;
            break;
        default: {
            size_t acc_off = GICD_REG_MASK(acc->addr);
            if (GICD_IS_REG(IPRIORITYR, acc_off)) {
                handler_info = &ipriorityr_info;
            } else if (GICD_IS_REG(ITARGETSR, acc_off)) {
                handler_info = &itargetr_info;
            } else if (GICD_IS_REG(IROUTER, acc_off)) {
                handler_info = &irouter_info;
            } else if (GICD_IS_REG(ID, acc_off)) {
                handler_info = &vgicd_pidr_info;
            } else {
                handler_info = &razwi_info;
            }
        }
    }

    if (vgic_check_reg_alignment(acc, handler_info)) {
        spin_lock(&cpu.vcpu->vm->arch.vgicd.lock);
        handler_info->reg_access(acc, handler_info, false, cpu.vcpu->id);
        spin_unlock(&cpu.vcpu->vm->arch.vgicd.lock);
        return true;
    } else {
        return false;
    }
}

/**
 * 功能描述: vgic发送软中断消息
 * 入口参数: vcpu,      指向发送软中断的虚拟核数据结构指针
 *           pcpu_mask, 目标物理核列表
 *           int_id,    软中断号
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void vgic_send_sgi_msg(struct vcpu *vcpu, cpumap_t pcpu_mask, irqid_t int_id)
{
    struct cpu_msg msg = {
        VGIC_IPI_ID,
        VGIC_INJECT,
        VGIC_MSG_DATA(cpu.vcpu->vm->id, 0, int_id, 0, cpu.vcpu->id)
    };

    for (size_t i = 0; i < platform.cpu_num; i++) {
        if (pcpu_mask & (1ull << i)) {
            cpu_send_msg(i, &msg);
        }
    }
}

/**
 * 功能描述: vgic设置虚拟中断对应的硬件信息
 * 入口参数: vm,    VM数据结构
 *           id,    虚拟中断号
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void vgic_set_hw(struct vm *vm, irqid_t id)
{
    if (id < GIC_MAX_SGIS) return;

    struct vgic_int *interrupt = NULL;

    if (id < GIC_CPU_PRIV) {
        list_foreach(vm->vcpu_list, struct vcpu, vcpu)
        {
            interrupt = vgic_get_int(vcpu, id, vcpu->id);
            if (interrupt != NULL) {
                spin_lock(&interrupt->lock);
                interrupt->hw = true;
                spin_unlock(&interrupt->lock);
            }
        }
    } else {
        /**
         * This assumes this method is called only during VM initlization
         */
        interrupt = vgic_get_int((struct vcpu *)list_peek(&vm->vcpu_list), id, 0);
        if (interrupt != NULL) {
            spin_lock(&interrupt->lock);
            interrupt->hw = true;
            spin_unlock(&interrupt->lock);
        } else {
            WARNING("trying to link non-existent virtual irq to physical irq")
        }
    }
}

/**
 * 功能描述: vgic 获取中断线数量
 * 入口参数: gic_dscrp, 通用中断控制器描述
 * 出口参数: void
 * 返 回 值: uint64_t,  返回中断线数量
 * 修改日期: 2022-09-21
 */
size_t vgic_get_itln(const struct gic_dscrp *gic_dscrp) {

    /**
     * By default the guest sees the real platforms interrupt line number
     * in the virtual gic. However a user can control this using the 
     * interrupt_num in the platform description configuration which be at
     * least the number os ppis and a multiple of 32.
     */

    size_t vtyper_itln =
        bit32_extract(gicd.TYPER, GICD_TYPER_ITLN_OFF, GICD_TYPER_ITLN_LEN);

    if(gic_dscrp->interrupt_num > GIC_MAX_PPIS) {
        vtyper_itln = (ALIGN(gic_dscrp->interrupt_num, 32)/32 - 1) & 
            BIT32_MASK(0, GICD_TYPER_ITLN_LEN);
    }

    return vtyper_itln;
}

/****************************************************************************
 ****                         私有函数定义                               ****
 ****************************************************************************/
/**
 * 功能描述: EOI维护中断处理函数
 * 入口参数: arg: 为了函数保持统一，添加的参数，未使用
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
static void vgic_handle_trapped_eoir(struct vcpu *vcpu)
{
    int64_t     lr_ind  = -1;
    uint64_t    eisr    = 0;

    while (
        eisr = gich_get_eisr(),
        (lr_ind = bitmap_find_nth((bitmap_t*)&eisr, g_num_lrs, 1, 0, true)) >= 0) {
        /* 读取列表寄存器，并对其清零 */
        unsigned long lr_val = gich_read_lr(lr_ind);
        gich_write_lr(lr_ind, 0);

        /* 获取中断信息 */
        struct vgic_int *interrupt =
            vgic_get_int(vcpu, GICH_LR_VID(lr_val), vcpu->id);
        if (interrupt == NULL) continue;

        /* 如果是软中断，则将其添加到列表寄存器（软中断是一个虚拟信号）。
         * 如果是SPI和PPI外设中断，则虚拟核只需交出所有权即可。
         * 因为，外设中断添加列表寄存器的过程是在中断响应处理程序中完成。
         */
        spin_lock(&interrupt->lock);
        interrupt->in_lr = false;
        if (interrupt->id < GIC_MAX_SGIS) {
            vgic_add_lr(vcpu, interrupt);
        } else {
            vgic_yield_ownership(vcpu, interrupt);
        }
        spin_unlock(&interrupt->lock);
    }
}

/**
 * 功能描述: 根据中断ID和核ID，获取中断对应的数据结构
 * 入口参数: struct vcpu *vcpu:      虚拟核的数据结构指针
 *           uint64_t int_id:   中断ID
 *           uint64_t vgicr_id: 指定的虚拟redistributor的ID，其实就是虚拟目标核
 * 出口参数: void
 * 返 回 值: struct vgic_int *:      返回中断ID对应的中断数据结构
 * 修改日期: 2022-09-21
 */
static inline struct vgic_int *vgic_get_int(struct vcpu *vcpu, irqid_t int_id,
                                       vcpuid_t vgicr_id)
{
    /* 如果是核的私有中断（软中断和私有外设中断），
     * 找到对应的核，直接返回核自身的中断数据结构
     */
    if (int_id < GIC_CPU_PRIV) {
        struct vcpu *target_vcpu =
            vgicr_id == vcpu->id ? vcpu : vm_get_vcpu(vcpu->vm, vgicr_id);
        return &target_vcpu->arch.vgic_priv.interrupts[int_id];
    }
    /* 如果是共享外设中断(SPI)，则返回虚拟机全局的中断数据结构 */
    else if (int_id < vcpu->vm->arch.vgicd.int_num) {
        return &vcpu->vm->arch.vgicd.interrupts[int_id - GIC_CPU_PRIV];
    }

    return NULL;
}

/**
 * 功能描述: 判断虚拟中断是不是由硬件产生、管理的中断
 * 入口参数: interrupt: 指向要写入空列表寄存器的虚拟中断的指针
 * 出口参数: void
 * 返 回 值: bool - 如果不是软中断，则返回true；否则返回false
 * 修改日期: 2022-09-21
 */
static inline bool vgic_int_is_hw(struct vgic_int *interrupt)
{
    return !(interrupt->id < GIC_MAX_SGIS) && interrupt->hw;
}

/**
 * 功能描述: 将虚拟中断写入列表寄存器
 * 入口参数: vcpu:          虚拟中断对应的虚拟核的指针
 *           interrupt:     指向要写入空列表寄存器的虚拟中断的指针
 *           lr_ind:        列表寄存器的索引 
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
static inline void vgic_write_lr(struct vcpu *vcpu, struct vgic_int *interrupt,
                                 size_t lr_ind)
{
    /* 取出当前索引指向的列表寄存器中的中断ID */
    irqid_t prev_int_id = vcpu->arch.vgic_priv.curr_lrs[lr_ind];

    /* 如果之前的中断ID不等于这次要写入的中断ID 且
     * 之前的中断ID不是私有中断，则应该将之前的中断移出列表寄存器。
     */
    if ((prev_int_id != interrupt->id) && !gic_is_priv(prev_int_id)) {
        struct vgic_int *prev_interrupt = vgic_get_int(vcpu, prev_int_id, vcpu->id);
        if (prev_interrupt != NULL) {
            spin_lock(&prev_interrupt->lock);
            if (vgic_owns(vcpu, prev_interrupt) && prev_interrupt->in_lr &&
                (prev_interrupt->lr == lr_ind)) {
                prev_interrupt->in_lr = false;
                vgic_yield_ownership(vcpu, prev_interrupt);
            }
            spin_unlock(&prev_interrupt->lock);
        }
    }

    /* 获取中断状态 */
    unsigned state = vgic_get_state(interrupt);

    /* 构造要写入列表寄存器的值 */
    unsigned long lr = ((interrupt->id << GICH_LR_VID_OFF) & GICH_LR_VID_MSK);

    /*
     * GICv2和GICv3&v4版本的列表寄存器的标志位是不一样的
     * 所以，需要分别处理。
     */
#if (GIC_VERSION == GICV2)
    lr |= ((unsigned long)(interrupt->prio >> 3) << GICH_LR_PRIO_OFF) &
          GICH_LR_PRIO_MSK;
#else
    lr |= (((unsigned long)interrupt->prio << GICH_LR_PRIO_OFF) & GICH_LR_PRIO_MSK) |
          GICH_LR_GRP_BIT;
#endif

    if (vgic_int_is_hw(interrupt)) {
        lr |= GICH_LR_HW_BIT;
        lr |= (((unsigned long)interrupt->id) << GICH_LR_PID_OFF) & GICH_LR_PID_MSK;
        if (state == PENDACT) {
            lr |= GICH_LR_STATE_ACT;
        } else {
            lr |= ((unsigned long)state << GICH_LR_STATE_OFF) & GICH_LR_STATE_MSK;
        }
    }
#if (GIC_VERSION == GICV2)
    else if (interrupt->id < GIC_MAX_SGIS) {
        if (state & ACT) {
            lr |= (interrupt->sgi.act << GICH_LR_CPUID_OFF) & GICH_LR_CPUID_MSK;
            lr |= GICH_LR_STATE_ACT;
        } else {
            for (ssize_t i = GIC_MAX_TARGETS - 1; i >= 0; i--) {
                if (interrupt->sgi.pend & (1U << i)) {
                    lr |= (i << GICH_LR_CPUID_OFF) & GICH_LR_CPUID_MSK;
                    interrupt->sgi.pend &= ~(1U << i);

                    lr |= GICH_LR_STATE_PND;
                    break;
                }
            }
        }

        if (interrupt->sgi.pend) {
            lr |= GICH_LR_EOI_BIT;
        }

    }
#endif
    else {
        if (!gic_is_priv(interrupt->id) && !vgic_int_is_hw(interrupt)) {
            lr |= GICH_LR_EOI_BIT;
        }

        lr |= ((unsigned long)state << GICH_LR_STATE_OFF) & GICH_LR_STATE_MSK;
    }

    interrupt->state = 0;
    interrupt->in_lr = true;
    interrupt->lr = lr_ind;
    vcpu->arch.vgic_priv.curr_lrs[lr_ind] = interrupt->id;
    gich_write_lr(lr_ind, lr);
}

/**
 * 功能描述: 判断中断是否绑定到虚拟核vcpu
 * 入口参数: struct vcpu *vcpu:          指向虚拟核vcpu的指针
 *           struct vgic_int *interrupt: 指向中断数据结构的指针
 * 出口参数: void
 * 返 回 值: bool： 匹配则返回ture，否则返回false
 * 修改日期: 2022-09-21
 */
static bool vgic_owns(struct vcpu *vcpu, struct vgic_int *interrupt)
{
    return interrupt->owner == vcpu;
}

/**
 * 功能描述: 获取中断在列表寄存器中的状态
 * 入口参数: struct vgic_int *interrupt: 指向中断数据结构的指针
 * 出口参数: void
 * 返 回 值: bool： 匹配则返回ture，否则返回false
 * 修改日期: 2022-09-21
 */
static inline uint8_t vgic_get_state(struct vgic_int *interrupt)
{
    uint8_t         state = 0;      /* 保存中断状态 */
    unsigned long   lr_val = 0;     /* 保存列表寄存器的值 */

    if (gich_get_lr(interrupt, &lr_val) >= 0) {
        state = GICH_LR_STATE(lr_val);
    } else {
        state = interrupt->state;
    }

    /* TODO: GICv2的软中断特殊状态，难道其pending状态在列表寄存器中没有反映？*/
#if (GIC_VERSION == GICV2)
    if (interrupt->id < GIC_MAX_SGIS && interrupt->sgi.pend) {
        state |= PEND;
    }
#endif

    return state;
}

/**
 * 功能描述: 判断中断是否绑定到虚拟核vcpu
 * 入口参数: struct vgic_int *interrupt: 指向中断数据结构的指针
 *           uint64_t *lr:          指向中断对应的列表寄存器中的值的指针
 * 出口参数: uint64_t *lr:          指向中断对应的列表寄存器中的值的指针
 * 返 回 值: int64_t:  匹配则返回列表寄存器的值，否则返回-1
 * 修改日期: 2022-09-21
 */
static inline int64_t gich_get_lr(struct vgic_int *interrupt, unsigned long *lr)
{
    /* 非法参数判断
     * 如果中断不在列表寄存器，或中断的所有者不等于当前的物理核，则返回-1
     */
    if (!interrupt->in_lr || interrupt->owner->phys_id != cpu.id) {
        return -1;
    }

    /* 读取列表寄存器，判断中断ID是否相等且中断处于活动状态，返回寄存器的值 */
    unsigned long lr_val = gich_read_lr(interrupt->lr);
    if ((GICH_LR_VID(lr_val) == interrupt->id) &&
        (GICH_LR_STATE(lr_val) != INV)) {
        if (lr != NULL) *lr = lr_val;
        return interrupt->lr;
    }

    return -1;
}

/**
 * 功能描述: 判断中断是否绑定到虚拟核vcpu
 * 入口参数: struct vcpu *vcpu: 指向虚拟中断应该绑定的虚拟核的数据结构
 * 出口参数: 
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
static void vgic_refill_lrs(struct vcpu *vcpu)
{
    /* 判断列表寄存器中是否有pending的中断 */
    bool has_pend = false;
    for (size_t i = 0; i < g_num_lrs; i++) {
        unsigned long lr = gich_read_lr(i);
        if (GICH_LR_STATE(lr) & PEND) {
            has_pend = true;
            break;
        }
    }

    /**
     * TODO: the following cycle can be highly otpimized using per-vcpu
     * active/pending interrupt lists.
     * 遍历列表寄存器
     */
    int64_t lr_ind;
    uint64_t elrsr;
    while (elrsr = gich_get_elrsr(),
           (lr_ind = bitmap_find_nth((bitmap_t*)&elrsr, g_num_lrs, 1, 0, true)) >=
               0) {
        struct vgic_int *interrupt = NULL;
        bool prev_pend = false;
        uint8_t prev_prio = GIC_LOWEST_PRIO;

        for (size_t i = 0; i < gic_num_irqs(); i++) {
            struct vgic_int *temp_int = vgic_get_int(vcpu, i, vcpu->id);
            if (temp_int == NULL) break;
            spin_lock(&temp_int->lock);
            if (vgic_get_ownership(vcpu, temp_int)) {
                uint8_t temp_state = vgic_get_state(temp_int);
                bool cpu_is_target = vgic_int_vcpu_is_target(vcpu, temp_int);
                if (cpu_is_target && temp_state != INV && !temp_int->in_lr) {
                    bool is_higher_prio = temp_int->prio < prev_prio;
                    bool is_act = (temp_state & ACT) != 0;
                    bool is_pend = (temp_state & PEND) != 0;
                    bool is_first_pend = !has_pend && is_pend && !prev_pend;
                    bool is_act_after_pend = has_pend && is_act && prev_pend;
                    if ((interrupt == NULL) || is_first_pend ||
                        is_act_after_pend || is_higher_prio) {
                        prev_pend = is_pend;
                        prev_prio = temp_int->prio;
                        struct vgic_int *aux = interrupt;
                        interrupt = temp_int;
                        temp_int = aux;
                    }
                }
            }

            if (temp_int != NULL) {
                vgic_yield_ownership(vcpu, temp_int);
                spin_unlock(&temp_int->lock);
            }
        }

        if (interrupt != NULL) {
            vgic_write_lr(vcpu, interrupt, lr_ind);
            has_pend = has_pend || prev_pend;
            spin_unlock(&interrupt->lock);
        } else {
            gich_set_hcr(gich_get_hcr() & ~(GICH_HCR_NPIE_BIT));
            break;
        }
    }
}

/**
 * 功能描述: 判断中断是否绑定到虚拟核vcpu
 * 入口参数: struct vcpu *vcpu: 指向虚拟中断应该绑定的虚拟核的数据结构
 * 出口参数: 
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
static void vgic_route(struct vcpu *vcpu, struct vgic_int *interrupt)
{
    /* 中断无效、或中断未使能，则直接返回 */
    if ((interrupt->state == INV) || !interrupt->enabled) {
        return;
    }

    /* 将虚拟中断添加到列表寄存器中 */
    if (vgic_int_vcpu_is_target(vcpu, interrupt)) {
        vgic_add_lr(vcpu, interrupt);
    }

    /* 如果虚拟中断已经在列表寄存器中，或是其它虚拟目标核 */
    if (!interrupt->in_lr && vgic_int_has_other_target(vcpu, interrupt)) {
        struct cpu_msg msg = {
            VGIC_IPI_ID,
            VGIC_ROUTE,
            VGIC_MSG_DATA(vcpu->vm->id, vcpu->id, interrupt->id, 0, 0)
        };

        /**
         * 1. 该虚拟核让出虚拟中断所有权
         * 2. 发送核间中断消息
         */
        vgic_yield_ownership(vcpu, interrupt);
        cpumap_t trgtlist =
            vgic_int_ptarget_mask(vcpu, interrupt) & ~(1ull << vcpu->phys_id);
        for (size_t i = 0; i < platform.cpu_num; i++) {
            if (trgtlist & (1ull << i)) {
                cpu_send_msg(i, &msg);
            }
        }
    }
}

/**
 * 功能描述: 虚拟GIC-核间中断处理程序
 *           收到物理核间中断，根据消息中的event信息，作出相应处理：
 *           1. 更新：更新虚拟化使能标志位
 *           2. 路由：将物理中断转换成虚拟中断，然后添加到列表寄存器中
 *           3. 注入：将物理中断转换成虚拟中断，注入到VM
 *           3. 设置：收到设置虚拟中断寄存器的事件，更新值并添加到列表寄存器中
 * 入口参数: event,     用于vgic的核间中断所传递的事件（event）
 *           data,      消息体中包含的数据
 * 出口参数: 
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
static void vgic_ipi_handler(uint32_t event, uint64_t data)
{
    uint16_t vm_id      = VGIC_MSG_VM(data);
    uint16_t vgicr_id   = VGIC_MSG_VGICRID(data);
    irqid_t int_id      = VGIC_MSG_INTID(data);
    uint64_t val        = VGIC_MSG_VAL(data);

    if (vm_id != cpu.vcpu->vm->id) {
        ERROR("received vgic3 msg target to another vcpu");
        // TODO: need to fetch vcpu from other vm if the taget vm for this
        // is not active
    }

    switch (event) {
        case VGIC_UPDATE_ENABLE: {
            vgic_update_enable(cpu.vcpu);
        } break;

        case VGIC_ROUTE: {
            struct vgic_int *interrupt =
                vgic_get_int(cpu.vcpu, int_id, cpu.vcpu->id);
            if (interrupt != NULL) {
                spin_lock(&interrupt->lock);
                if (vgic_get_ownership(cpu.vcpu, interrupt)) {
                    if (vgic_int_vcpu_is_target(cpu.vcpu, interrupt)) {
                        vgic_add_lr(cpu.vcpu, interrupt);
                    }
                    vgic_yield_ownership(cpu.vcpu, interrupt);
                }
                spin_unlock(&interrupt->lock);
            }
        } break;

        /* 收到注入事件：将物理中断转换成虚拟中断，注入到VM */
        case VGIC_INJECT: {
            vgic_inject(&cpu.vcpu->vm->arch.vgicd, int_id, val);
        } break;

        /* 收到设置虚拟寄存器的事件 */
        case VGIC_SET_REG: {
            uint64_t    reg_id = VGIC_MSG_REG(data);
            struct      vgic_reg_handler_info *handlers =
                    vgic_get_reg_handler_info(reg_id);
            struct vgic_int *interrupt = vgic_get_int(cpu.vcpu, int_id, vgicr_id);
            if (handlers != NULL && interrupt != NULL) {
                vgic_int_set_field(handlers, cpu.vcpu, interrupt, val);
            }
        } break;
    }
}

/**
 * 功能描述: 虚拟GIC-设置虚拟中断寄存器
 *           更新虚拟核的中断寄存器信息，并将虚拟中断添加到列表寄存器中
 * 入口参数: vcpu,  指向虚拟中断应该绑定的虚拟核的数据结构
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
static void vgic_int_set_field(
        struct vgic_reg_handler_info *handlers,
        struct vcpu *vcpu,
        struct vgic_int *interrupt,
        uint64_t data)
{
    spin_lock(&interrupt->lock);
    if (vgic_get_ownership(vcpu, interrupt)) {
        vgic_remove_lr(vcpu, interrupt);
        if (handlers->update_field(vcpu, interrupt, data) &&
            vgic_int_is_hw(interrupt)) {
            handlers->update_hw(vcpu, interrupt);
        }
        vgic_route(vcpu, interrupt);
        vgic_yield_ownership(vcpu, interrupt);
    } else {
        struct cpu_msg msg = {
            VGIC_IPI_ID,
            VGIC_SET_REG,
            VGIC_MSG_DATA(vcpu->vm->id, 0, interrupt->id, handlers->regid, data)
        };
        cpu_send_msg(interrupt->owner->phys_id, &msg);
    }
    spin_unlock(&interrupt->lock);
}

/**
 * 功能描述: 虚拟GIC-设置虚拟化使能
 * 入口参数: vcpu,  指向虚拟中断应该绑定的虚拟核的数据结构
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
static inline void vgic_update_enable(struct vcpu *vcpu)
{
    if (cpu.vcpu->vm->arch.vgicd.CTLR & VGIC_ENABLE_MASK) {
        gich_set_hcr(gich_get_hcr() | GICH_HCR_En_BIT);
    } else {
        gich_set_hcr(gich_get_hcr() & ~GICH_HCR_En_BIT);
    }
}

/**
 * 功能描述: 
 * 入口参数: vcpu,  指向虚拟中断应该绑定的虚拟核的数据结构
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
static void vgic_eoir_highest_spilled_active(struct vcpu *vcpu)
{
    struct vgic_int *interrupt = NULL;
    for (size_t i = 0; i < gic_num_irqs(); i++) {
        struct vgic_int *temp_int = vgic_get_int(vcpu, i, vcpu->id);
        if (temp_int == NULL) break;

        spin_lock(&temp_int->lock);
        if (vgic_get_ownership(vcpu, temp_int) && (temp_int->state & ACT)) {
            if (interrupt == NULL || (interrupt->prio < temp_int->prio)) {
                struct vgic_int *aux = interrupt;
                interrupt = temp_int;
                temp_int = aux;
            }
        }

        if (temp_int != NULL) {
            vgic_yield_ownership(vcpu, temp_int);
            spin_unlock(&temp_int->lock);
        }
    }

    if (interrupt) {
        interrupt->state &= ~ACT;
        if (vgic_int_is_hw(interrupt)) {
            gic_set_act(interrupt->id, false);
        } else {
            if (interrupt->state & PEND) {
                vgic_add_lr(vcpu, interrupt);
            }
        }
        spin_unlock(&interrupt->lock);
    }
}
